/*
 * File:   GameState.h
 * Author: root
 *
 * Created on November 13, 2008, 7:39 PM
 */
#ifndef _GAMESTATE_H
#define	_GAMESTATE_H

#include "CCardStack.h"
#include "Move.h"

#define NUM_PLAYERS 2
#define NUM_CARDS 52
#define INVALID_CARD 53
#define DEAL_ROUND -1

namespace Card {
  enum State {
    NotTouched=0,
    Drawn=1,
    PickedUp=2,
    Discarded=4
  };

  enum Stack {
    InDeck=0,
    InDiscard=1,
    InPlayerHand=2
  };

  struct Location {
    Stack stack;
    char player;
  };
}

enum PlayerPhase {NoGame, DrawPhase, DiscardPhase, GameOver};
typedef std::vector<Move> MoveHistory;

class GameState {

    Card::Location cardLocation[NUM_CARDS];
    bool isKnown[NUM_CARDS];    // Known cards are the ones that have been discarded at some point
    char cardHistory[NUM_PLAYERS][NUM_CARDS];
    MoveHistory visibleMoveHistory[NUM_PLAYERS];
    int lastPickUpRound[NUM_PLAYERS];
    CCardStack deck;
    CCardStack discard;
//     CCardStack playerCards[NUM_PLAYERS];    // Cards that are known to be in a player's hand (picked up from discard and not discarded)
    char round;
    int currPlayer;
    PlayerPhase currPhase;
    bool knocked;
    int knockPlayer;

    void advancePlayer();

public:

    // Strategy-specific state

// OppSuitTrackDiscardStrategy objects
    int suitHistory[NUM_PLAYERS][4];
    // PointBracketing strategies
    int positiveSuitHistory[NUM_PLAYERS][4];
    int minPoints[NUM_PLAYERS];
    int scoringSuit[NUM_PLAYERS];

    // End strategy-specific state

    GameState();

//     void setNumPlayers();
    CCardStack deal() {return deal(currPlayer);}
    CCard draw() {return draw(currPlayer);}
    CCard pickUp() {return pickUp(currPlayer);}
    void doDiscard(const CCard discarded) {
      return doDiscard(discarded,currPlayer);
    }
    void knock() {knock(currPlayer);}

    CCardStack deal(int player);
    CCard draw(int player);
    CCard pickUp(int player);
    void doDiscard(CCard discarded, int player);
    void knock(int player);
    void report31(int player);

    int getCurrRound() const {
      return round;
    }
    int getCurrPlayer() const {
      return currPlayer;
    }
    CCardStack getCardsInDiscard() const {
      return discard;
    }
    PlayerPhase getCurrPhase() const {
      return currPhase;
    }
    CCardStack getCardsDiscardedByPlayer(int player) const;
    CCardStack getCardsPickedUpByPlayer(int player) const;
    CCardStack getCardsPickedUpAndHeldByPlayer(int player) const;
    CCardStack getCardsShown() const;
    CCardStack getCardsNotShown() const;
    CCardStack getUnknownCards(int playerPerspective) const;
    float singleDrawProbability(int playerPerspective) const;
//    int powerOfCard(int playerPerspective, const CCard& card) const;   // Define the power of a card as the ranking of its value (0 to 100) in the values of the remaining possible cards for a player
    const MoveHistory* getPlayerMoveHistory(int player) const;
    Move getPlayersLastMove(int player) const;
    Move getPlayersLastPickUpMove(int player) const;

    bool isLastRound() const {
        return knocked;
    }
    bool deckIsEmpty() const {
      return deck.Empty();
    }

    const CCardStack& getDrawStack() const {
      return deck;
    }
    const CCardStack& getDiscardStack() const {
      return discard;
    }
};

#endif	/* _GAMESTATE_H */

